////
//// Created by 17775 on 2024/6/17.
////
//
//#include <winsock2.h>
//#include <IPHlpApi.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <atltypes.h>
//
//#pragma comment(lib, "IPHlpApi.lib")
//#pragma comment(lib, "ws2_32.lib")
//#include "BeamProfiler.h"
//
//BeamProfiler::BeamProfiler()
//{
//    _strIP = "";
//    _strPort = "";
//    _nDocIdLive = 0;
//    _bUseOpenLive = FALSE;
//    _dwCamIdLow = 0;
//    _dwCamIdHigh = 0;
//    _bCropToAoi = FALSE;
//    _bCropToAoiAvailable = FALSE;
//    _nDocIdMeasure = 0;
//}
//
//bool BeamProfiler::Connect() {
//    // list of possible XmlRpc client ports
//    WORD nClientPorts[] = { 8000, 8080, 8008, 80 };
//
//    _strIP = "127.0.0.1";
//    const char* szAddr = _strIP.data();
//
//    // select a possible client port
//    WORD nClientPort = nClientPorts[0];
//    for (int i = 0; i < _countof(nClientPorts); i++)
//    {
//        if (IsPortAvailable(nClientPorts[i]))
//        {
//            nClientPort = nClientPorts[i];
//            break;
//        }
//    }
//
//    _strPort = "8081";
//
//    // open connection to RayCi
//    int nPort = atoi(_strPort.data());
//    if (RayCi_connectA(szAddr, nPort, nClientPort)){
//        // register callback
//        RayCi_Callback_register_onExit(&CallbackRayCi_onExit, this, &_nIdCallback_RayCiClosed);
//        QueryCameraList();
//        ConnectionToLiveMode();
//        if (!_vecCameras.empty())
//        {
//            RayCi_Windows_GlobalSettings_hide();
//            //RayCi_Windows_Main_hide();
//            RayCi_Windows_Messages_hide();
//            bool bValid = false;
//            bool bCanSave = false;
//            RayCi_LiveMode_Background_isValid(_nDocIdLive, &bValid);
//            if (!bValid)
//            {
//                RayCi_LiveMode_Background_load(_nDocIdLive);
//                do
//                {
//                    RayCi_LiveMode_Background_canSave(_nDocIdLive, &bCanSave);
//                    if (!bCanSave)
//                    {
//                        Sleep(100);
//                    }
//                } while (!bCanSave); // blocked
//            }
//            else
//            {
//                RayCi_LiveMode_Background_canSave(_nDocIdLive, &bCanSave);
//                if (bCanSave)
//                {
//                    RayCi_LiveMode_Background_save(_nDocIdLive);
//                }
//            }
//            RayCi_LiveMode_Background_setApply(_nDocIdLive, true);
//        }
//        RayCi_LiveMode_Settings_Lut_setAutoContrast(_nDocIdLive, true);
//        return TRUE;
//    }
//    else {
//        RayCi_disconnect();
//    }
//    return FALSE;
//}
//
////BOOL BeamProfiler::Init()
////{
////    BOOL bRet = FALSE;
////    string::size_type pos = g_systemCfgParas.m_sysParsCommunication._strSpotAnalyzer.find(",");
////    if (pos	!= g_systemCfgParas.m_sysParsCommunication._strSpotAnalyzer.npos)
////    {
////        if (atoi(g_systemCfgParas.m_sysParsCommunication._strSpotAnalyzer.substr(0, pos).data()) == 1)
////        {
////            string strCommucation = g_systemCfgParas.m_sysParsCommunication._strSpotAnalyzer.substr(pos + 1);
////            pos = strCommucation.find(",");
////            _strIP = strCommucation.substr(0, pos);
////            _strPort = strCommucation.substr(pos+1);
////            Connect();
////        }
////    }
////    return bRet;
////}
//
//void BeamProfiler::CallbackRayCi_onExit(IN void* pContext){
//    BeamProfiler* pThis = reinterpret_cast<BeamProfiler *>(pContext);
//    if (pThis) {
//        emit pThis->RayCi_Closed();
//    }
//}
//
//void BeamProfiler::RayCi_Closed(){
//
//}
//
//void BeamProfiler::ConnectionToLiveMode()
//{
//    if (_nDocIdLive != 0)
//    {
//        // check if this LiveMode is available
//        int nDocIdLive[8];
//        int nDocIdLiveSize = 8;
//        if (RayCi_LiveMode_list(nDocIdLive, &nDocIdLiveSize))
//        {
//            bool bFound = false;
//            for (int i = 0; i < nDocIdLiveSize; i++)
//            {
//                if (nDocIdLive[i] == _nDocIdLive)
//                {
//                    bFound = true;
//                    break;
//                }
//            }
//            if (!bFound)
//            {
//                CloseLiveMode();
//            }
//        }
//    }
//
//    // get new LiveMode ID
//    if (_nDocIdLive == 0)
//    {
//        // query list of already connected cameras, we use only the first one
//        int	nDocIdLive = 0;
//        int	nDocIdLiveSize = 1;
//        RayCi_LiveMode_list(&nDocIdLive, &nDocIdLiveSize);
//        if (nDocIdLive != 0)
//        {
//            // use already opened live mode
//            _bUseOpenLive = TRUE;
//            _nDocIdLive = nDocIdLive;
//        }
//        else {
//            // open a new live mode with default camera id
//            _bUseOpenLive = FALSE;
//            _nDocIdLive = 0;
//            if (!RayCi_LiveMode_open(0, 0, &_nDocIdLive))
//            {
//                cout << "LiveMode could not be opened." << endl;
//            }
//        }
//    }
//
//    if (_nDocIdLive != 0)
//    {
//        // if we can open a LiveMode, the camera list should not be empty
//        if (_vecCameras.empty())
//            QueryCameraList();
//
//        //start worker thread
////        _evCancelGetNewFrame.ResetEvent();
////        _evStartGetNewFrame.ResetEvent();
//
////        m_workerThread = std::thread(&BeamProfiler::Worker_GetNewFrame, this);
//        m_workerThread.detach();
//
//        // register call back
//        RayCi_Callback_register_Document_onClose(&CallbackRayCi_Document_onClose, this,
//                                                 _nDocIdLive, &_nIdCallback_LiveModeClosed);
//        RayCi_Callback_register_LiveMode_Data_onNewFrame(&CallbackRayCi_LiveMode_onNewFrame, this,
//        	_nDocIdLive, &_nIdCallback_LiveModeNewFrame);
//        RayCi_Callback_register_LiveMode_Camera_onCameraRemoved(&CallbackRayCi_LiveMode_onCameraRemoved,
//                                                                this, _nDocIdLive, &_nIdCallback_LiveModeCameraRemoved);
//
//        // query current camera ID, available from RayCi version 2.3.7
//        int nCamIdHigh = 0, nCamIdLow = 0;
//        if (RayCi_LiveMode_Camera_getIdCurrentCam(_nDocIdLive, &nCamIdHigh, &nCamIdLow, NULL, NULL, NULL, NULL))
//        {
//            _dwCamIdLow = nCamIdLow;
//            _dwCamIdHigh = nCamIdHigh;
//        }
//        QueryCameraParameter();
//    }
//}
//
////DWORD BeamProfiler::Worker_GetNewFrame(){
////
////}
//
////DWORD BeamProfiler::Worker_GetNewFrame()
////{
////    std::vector<float> vecData;
////    std::vector<BYTE>  vecPreview;
////
//////    WaitForSingleObject(_evStartGetNewFrame, INFINITE);
//////    if (WaitForSingleObject(_evCancelGetNewFrame, 0) != WAIT_TIMEOUT)
//////        return 0;//break;
////
////    _nFrameNrRetrieve = _nFrameNrCallback;
////    const int nDocId = _nDocIdLive;
////    int nSizeX = 0, nSizeY = 0;
////    if (RayCi_LiveMode_Data_getSizeX(nDocId, &nSizeX) && RayCi_LiveMode_Data_getSizeY(nDocId, &nSizeY))
////    {
////        if ((nSizeX > 0) && (nSizeY > 0))
////        {
////            BOOL bSuccessful = FALSE;
////            BOOL bEraseBg = FALSE;
////
////            if (!bSuccessful && _bCropToAoiAvailable && _bCropToAoi)
////            {
////                // Query only the bounding rectangle of the AOI as preview
////                // Query AOI parameter
////                int nShape = 0;
////                double dX0 = 0., dY0 = 0., dMajor = 0., dMinor = 0., dAngle = 0.;
////                if (RayCi_LiveMode_AOI_getPositionX_px(nDocId, &dX0) && RayCi_LiveMode_AOI_getPositionY_px(nDocId, &dY0) &&
////                    RayCi_LiveMode_AOI_getMajor_px(nDocId, &dMajor) && RayCi_LiveMode_AOI_getMinor_px(nDocId, &dMinor) &&
////                    RayCi_LiveMode_AOI_getAzimuthAngle_px(0, &dAngle) && RayCi_LiveMode_AOI_getShape(nDocId, &nShape))
////                {
////                    // convert angle: deg => rad
////                    // const double PI = M_PI;
////                    dAngle *= M_PI / 180.;
////
////                    // calculate left, right, top, bottom extension of the AOI
////                    double dLeft = 0., dTop = 0., dRight = nSizeX - 1, dBottom = nSizeY - 1;
////                    switch (nShape)
////                    {
////                        case 1:
////                        {
////                            // Rectangle
////                            const double ca = cos(dAngle);
////                            const double sa = sin(dAngle);
////                            const double MajorX = 0.5*ca*dMajor;
////                            const double MajorY = 0.5*sa*dMajor;
////                            const double MinorX = -0.5*sa*dMinor;
////                            const double MinorY = 0.5*ca*dMinor;
////                            {
////                                const double x0 = MajorX + MinorX;
////                                const double x1 = MajorX - MinorX;
////                                const double x2 = -MajorX + MinorX;
////                                const double x3 = -MajorX - MinorX;
////                                dLeft = dX0 + min(min(x0, x1), min(x2, x3));
////                                dRight = dX0 + max(max(x0, x1), max(x2, x3));
////                            }
////                            {
////                                const double y0 = MajorY + MinorY;
////                                const double y1 = MajorY - MinorY;
////                                const double y2 = -MajorY + MinorY;
////                                const double y3 = -MajorY - MinorY;
////                                dTop = dY0 + min(min(y0, y1), min(y2, y3));
////                                dBottom = dY0 + max(max(y0, y1), max(y2, y3));
////                            }
////                            break;
////                        }
////                        case 0:
////                        default:
////                        {
////                            // Ellipse, or else
////                            const double ca = cos(dAngle);
////                            const double sa = sin(dAngle);
////                            const double ca2 = ca*ca;
////                            const double sa2 = sa*sa;
////                            const double csa = ca*sa;
////                            const double Major2 = dMajor*dMajor;
////                            const double Minor2 = dMinor*dMinor;
////                            const double XX = Major2*ca2 + Minor2*sa2;		 // + 2*XY*csa;
////                            const double XY = csa*(Major2 - Minor2);        // + XY*(ca2-sa2);
////                            const double YY = Major2*sa2 + Minor2*ca2;    // - 2*XY*csa;
////                            //const double Disc= XX*YY - XY*XY;
////                            const double x12 = sqrt(XX);
////                            const double y12 = sqrt(YY);
////                            dLeft = dX0 - 0.5*x12;
////                            dRight = dX0 + 0.5*x12;
////                            dTop = dY0 - 0.5*y12;
////                            dBottom = dY0 + 0.5*y12;
////                            break;
////                        }
////                    }
////
////                    // round to int
////                    int nLeft = int(dLeft);
////                    int nRight = int(dRight + 1.);
////                    int nTop = int(dTop);
////                    int nBottom = int(dBottom + 1.);
////
////                    // crop to image
////                    nLeft = min(max(nLeft, 0), nSizeX - 1);
////                    nRight = min(max(nRight, 0), nSizeX - 1);
////                    nTop = min(max(nTop, 0), nSizeY - 1);
////                    nBottom = min(max(nBottom, 0), nSizeY - 1);
////                    int nWidth = nRight - nLeft + 1;
////                    int nHeight = nBottom - nTop + 1;
////
////                    if ((nWidth > 0) && (nHeight > 0))
////                    {
////                        int nSize = nWidth*nHeight;
////                        bEraseBg = (_sizeData != QSize(nWidth, nHeight));
//////                        _sizeData.SetSize(nWidth, nHeight);
////                        _sizeData.setWidth(nWidth);
////                        _sizeData.setHeight(nHeight);
////                        vecPreview.resize(nSize);
////                        // get rectangular as preview, available from RayCi version 2.3.7
////                        if (RayCi_LiveMode_Data_getPreviewRect(nDocId, nLeft, nTop, nWidth, nHeight, &vecPreview[0], &nSize))
////                        {
////                            _dataFormat = FORMAT_UINT8;
////
////                            // synchronize access to the image
////                            QMutexLocker lockImg(&_csecImageData);
////
////                            // check image size
////                            InitImage(nWidth, nHeight);
////
////                            // copy data to image
////                            for (int y = 0; y < nHeight; y++)
////                            {
//////                                memcpy(_imgData.GetPixelAddress(0, y), &vecPreview[y*nWidth], nWidth*sizeof(BYTE));
////
////                                // 获取指向图像第 y 行的指针
////                                BYTE* dest = _imgData.scanLine(y);
////
////                                // 复制数据
////                                memcpy(dest, &vecPreview[y * nWidth], nWidth * sizeof(BYTE));
////                            }
////                            bSuccessful = TRUE;
////                        }
////
////                    }
////                }
////            }
////
////            if (!bSuccessful)
////            {
////                // Query all data as preview
////
////                int nSize = nSizeX*nSizeY;
////                bEraseBg = (_sizeData != QSize(nSizeX, nSizeY));
//////                _sizeData.SetSize(nSizeX, nSizeY);
////                _sizeData.setWidth(nSizeX);
////                _sizeData.setHeight(nSizeY);
////                vecPreview.resize(nSize);
////                // get data as preview, available from RayCi version 2.3.7
////                if (RayCi_LiveMode_Data_getPreview(nDocId, &vecPreview[0], &nSize))
////                {
////                    _dataFormat = FORMAT_UINT8;
////
////                    // synchronize access to the image
////                    QMutexLocker lockImg(&_csecImageData);
////
////                    // check image size
////                    InitImage(nSizeX, nSizeY);
////
////                    // copy data to image
////                    for (int y = 0; y < nSizeY; y++)
////                    {
////                        // 获取指向图像第 y 行的指针
////                        BYTE* dest = _imgData.scanLine(y);
////
////                        // 复制数据
////                        memcpy(dest, &vecPreview[y * nSizeX], nSizeX * sizeof(BYTE));
////                    }
////                    bSuccessful = TRUE;
////                }
////            }
////
////            if (!bSuccessful)
////            {
////                // Preview is not available => use float data
////
////                int nSize = nSizeX*nSizeY;
////                bEraseBg = (_sizeData != QSize(nSizeX, nSizeY));
////                _sizeData.setWidth(nSizeX);
////                _sizeData.setHeight(nSizeY);
////                vecData.resize(nSize);
////                // get data as floating point
////                if (RayCi_LiveMode_Data_getFloatField(nDocId, &vecData[0], &nSize))
////                {
////                    _dataFormat = FORMAT_FLOAT;
////
////                    // synchronize access to the image
////                    QMutexLocker lockImg(&_csecImageData);
////
////                    // check image size
////                    InitImage(nSizeX, nSizeY);
////
////                    // convert data to image
////                    //#pragma omp parallel for				// OpenMP requires additional dependencies
////                    for (int y = 0; y < nSizeY; y++)
////                    {
////                        const float* pSrc = &vecData[y*nSizeX];
//////                        BYTE*  pDest = (BYTE*)_imgData.GetPixelAddress(0, y);
////                        // 获取指向图像第 y 行的指针
////                        BYTE* pDest = _imgData.scanLine(y);
////                        for (int x = 0; x < nSizeX; x++)
////                        {
////                            int  iVal = int(255.f*pSrc[x] + 0.5f); // round to nearest int
////                            BYTE bVal = min(max(iVal, 0), 255); // saturate
////                            pDest[x] = bVal;
////                        }
////                    }
////                    bSuccessful = TRUE;
////                }
////            }
////        }
////    }
////    else {
////        _sizeData.setWidth(0);
////        _sizeData.setHeight(0);
////    }
////    //}
////    return 0;
////}
//
//void BeamProfiler::InitImage(int cx, int cy)
//{
//    uint32_t nActualLut_buffer[256] = { 0 };
//    int iBufferSize = 256;
//
//    RayCi_LiveMode_Settings_Lut_setThreshold(_nDocIdLive, 0.0, 0.5);
//    RayCi_LiveMode_Settings_Lut_getActualLut(_nDocIdLive, 8, nActualLut_buffer, &iBufferSize);
//    //RayCi_LiveMode_Settings_Lut_getBaseLut(_nDocIdLive, nActualLut_buffer, &iBufferSize);
//
//    QMutexLocker lockImg(&_csecImageData);
//
//    if (_imgData.isNull() || (_imgData.width() != cx) || (_imgData.height() != cy))
//    {
//        QImage imgData(cx, cy, QImage::Format_Grayscale8); // 创建一个8位灰度图像
//        if (!_imgData.isNull()) {
//            // generate colored color table
//            QVector<QRgb> colorTable(256);
//            for (int i = 0; i < 256; ++i) {
//                uint32_t colorValue = nActualLut_buffer[i];
//                int r = (colorValue >> 16) & 0xFF;
//                int g = (colorValue >> 8) & 0xFF;
//                int b = colorValue & 0xFF;
//                colorTable[i] = qRgb(r, g, b);
//            }
//            _imgData.setColorTable(colorTable);
//        }
//    }
//}
//
//void BeamProfiler::CallbackRayCi_Document_onClose( IN void* pContext, IN int nIdDoc )
//{
//
//}
//
//void BeamProfiler::CallbackRayCi_LiveMode_onNewFrame(IN void* pContext, IN int nIdDoc, IN int nFrameNr, IN const tm* tmFrameTime, IN int nFrameTime_ms){
//
//}
//
//void BeamProfiler::CallbackRayCi_LiveMode_onCameraRemoved( IN void* pContext, IN int nIdDoc, IN int nIdCamHigh, IN int nIdCamLow )
//{
//
//}
//
//void BeamProfiler::CloseLiveMode()
//{
//    // unregister callbacks
//    if (_nIdCallback_LiveModeCameraRemoved != 0)
//    {
//        RayCi_Callback_unregisterById(_nIdCallback_LiveModeCameraRemoved);
//        _nIdCallback_LiveModeCameraRemoved = 0;
//    }
//    if (_nIdCallback_LiveModeClosed != 0)
//    {
//        // both methods are possible
//        RayCi_Callback_unregisterById(_nIdCallback_LiveModeClosed);
//        _nIdCallback_LiveModeClosed = 0;
//    }
//    if (_nIdCallback_LiveModeNewFrame != 0)
//    {
//        RayCi_Callback_unregisterById(_nIdCallback_LiveModeNewFrame);
//        _nIdCallback_LiveModeNewFrame = 0;
//    }
//
//    // stop worker thread
//    // _evCancelGetNewFrame.SetEvent();
//    // _evStartGetNewFrame.SetEvent();
//
//    if (_nDocIdLive != 0)
//    {
//        if (!_bUseOpenLive)
//            RayCi_LiveMode_close(_nDocIdLive, true);
//        _bUseOpenLive = false;
//        _nDocIdLive = 0;
//    }
//
//    if (_nDocIdMeasure != 0)
//    {
//        RayCi_closeDocument(_nDocIdMeasure, true);
//    }
//    _dwCamIdLow = 0;
//    _dwCamIdHigh = 0;
//}
//
//void BeamProfiler::QueryCameraParameter()
//{
//    // query exposure time list
//    int nListSize = 0;
//    _vecExposureTimes.clear();
//    if (RayCi_LiveMode_Camera_ExposureTime_getList(_nDocIdLive, NULL, &nListSize) && (nListSize > 0)) // nListSize = 19
//    {
//        _vecExposureTimes.resize(nListSize); // 19
//        RayCi_LiveMode_Camera_ExposureTime_getList(_nDocIdLive, &_vecExposureTimes.front(), &nListSize);
//    }
//
//    // query gain list
//    nListSize = 0;
//    _vecGain.clear();
//    if (RayCi_LiveMode_Camera_Gain_getList(_nDocIdLive, NULL, &nListSize) && (nListSize > 0))
//    {
//        _vecGain.resize(nListSize); // nListSize = 5
//        RayCi_LiveMode_Camera_Gain_getList(_nDocIdLive, &_vecGain.front(), &nListSize);
//    }
//}
//
//BOOL BeamProfiler::IsPortAvailable( WORD wPort ){
//    DWORD dwSize = 0;
//    GetTcpTable(NULL, &dwSize, TRUE); // query size
//    PMIB_TCPTABLE pTcpTable = (PMIB_TCPTABLE)_alloca(dwSize); // alloc memory on stack
//    if ( GetTcpTable(pTcpTable, &dwSize, TRUE) == NO_ERROR )
//    {
//        for (DWORD i = 0; i<pTcpTable->dwNumEntries; i++)
//        {
//            const MIB_TCPROW& entry = pTcpTable->table[i];
//            if ( (entry.dwState==MIB_TCP_STATE_LISTEN) && (ntohs((WORD)entry.dwLocalPort)==wPort) )
//            {
//                // port is already in use
//                return false;
//            }
//        }
//    }
//    return true;
//}
//
//void BeamProfiler::QueryCameraList()
//{
//    _vecCameras.clear();
//    // query list of all available cameras
//    int nCamListSize = 0;
//    // nIdDoc=-1: query list of connected cameras without LiveMode, available from RayCi version 2.3.7,
//    // otherwise a LiveMode has to be open before and nIdDoc=0
//    if (RayCi_LiveMode_Camera_getIdCamListSize(-1, &nCamListSize))
//    {
//        _bCropToAoiAvailable = TRUE; // available from RayCi version 2.3.7
//        for (int nItem = 0; nItem < nCamListSize; nItem++)
//        {
//            int nCamIdHigh = 0, nCamIdLow = 0;
//            char szCamName[80];
////            QString szCamName[80];
//            int nNameSize = _countof(szCamName);
//            if (RayCi_LiveMode_Camera_getIdCamListItemA(-1, nItem, &nCamIdHigh, &nCamIdLow, szCamName, &nNameSize, NULL, NULL))
//            {
//                _vecCameras.emplace_back(szCamName, nCamIdLow, nCamIdHigh);
//            }
//        }
//    }
//    else if (RayCi_LiveMode_Camera_getIdCamListSize(0, &nCamListSize)) // try any open LiveMode
//    {
//        for (int nItem = 0; nItem < nCamListSize; nItem++)
//        {
//            int   nCamIdHigh = 0, nCamIdLow = 0;
//            char szCamName[80];
//            int   nNameSize = _countof(szCamName);
//            if (RayCi_LiveMode_Camera_getIdCamListItemA(0, nItem, &nCamIdHigh, &nCamIdLow, szCamName, &nNameSize, NULL, NULL))
//            {
//                _vecCameras.emplace_back(szCamName, nCamIdLow, nCamIdHigh);
//            }
//        }
//    }
//}